<!-- 聊天页面 -->
<template>
  <div class="message-box" style="position: relative">
    <chat-info
      @reach-top="handleReachTop"
      @top-view="handleMoreView"
      @resetUploadSuccess="resetUploadSuccess"
      @recall="handleRecall"
      @resetEdit="handleResetEdit"
      :messageInfo="messageInfo"
      ref="messages"
    ></chat-info>
    <chat-edit
      ref="editor"
      @send="_handleSend"
      @upload="_handleUpload"
      @historyShowChange="historyShowChange"
    ></chat-edit>
    <el-drawer
      :modal="false"
      :visible.sync="groupRightShow"
      style="position: absolute; z-index: -1"
      :size="280"
      :before-close="handleClose"
    >
      <group-chat></group-chat>
    </el-drawer>

    <el-drawer
      :modal="false"
      title="聊天记录"
      :visible.sync="chatHistoryRightShow"
      style="position: absolute; z-index: -1"
      :size="280"
      :before-close="closeHistory"
    >
      <chat-history @close="closeHistory"></chat-history>
    </el-drawer>
  </div>
</template>

<script>
import { generateUUID } from "@/utils"
import chatEdit from "./edit.vue"
import chatInfo from "./info.vue"
import {
  createChat,
  getMessageList,
  messagesRecall,
  messagesSend
} from "@/api/chat"
import lockr from "lockr"
import { mapState } from "vuex"
import { isEmpty } from "@/utils/validate"
import groupChat from "@/components/right/groupChat.vue"
import {
  CHAT_STATUS,
  FILE_TYPE,
  getFileType,
  MESSAGE_TYPE
} from "@/utils/constant"
import chatHistory from "@/components/right/chatHistory.vue"
export default {
  name: "messagePage",
  components: { chatEdit, chatInfo, groupChat, chatHistory },
  props: {},
  data() {
    return {
      allMessages: [],
      messages: [],
      count: 10,
      groupRightShow: false,
      chatHistoryRightShow: false,
      // eslint-disable-next-line no-undef
      minioEndpoint_mini: minioEndpoint_mini,
      messageInfo: {
        messages: [],
        from: 1,
        size: 10,
        page: {
          chatIndexBegin: null,
          chatIndexEnd: null,
          lastCount: 10
        }
      }
    }
  },
  created() {},
  mounted() {
    // this.getMessageByList()
  },

  computed: {
    ...mapState({
      mqAction: (state) => state.mqttAction,
      userId: (state) => state.userInfo.userId,
      userInfo: (state) => state.userInfo,
      receiverId: (state) => state.receiverId,
      chatId: (state) => state.chatId,
      currentChat: (state) => state.currentChat,
      currentChatUserInfo: (state) => state.currentChatUserInfo
    }),
    lastIndex() {
      const data = this.messageInfo.messages
      return data && data.length > 0 ? data.slice(-1)[0].chatIndex : 0
    }
  },

  methods: {
    updateMessage() {
      this.getMessageByList()
    },
    resetMessageByList() {
      this.messageInfo = {
        messages: [],
        from: 1,
        size: 10,
        page: {
          chatIndexBegin: null,
          chatIndexEnd: undefined,
          lastCount: 10
        }
      }
      this.getMessageByList()
    },
    //获取消息
    async getMessageByList(scroll) {
      let params = {}
      // if (this.currentChat.status !== CHAT_STATUS.NORMAL && !scroll) {
      //   params = {
      //     chatIndexBegin: this.currentChat.readChatIndex - 9,
      //     chatIndexEnd: this.currentChat.readChatIndex,
      //     lastCount: undefined
      //   }
      // }
      const res = await getMessageList({
        conversation_id: this.currentChat.id,
        ...this.messageInfo.page,
        ...params
      })
      const data = isEmpty(res.data)
        ? []
        : res.data
            .map((item) => this.addImageDomain(item))
            .map((nextItem) => {
              return {
                ...nextItem,
                status: "end"
              }
            })

      if (isEmpty(data) || data.length < this.count) {
        await this.$nextTick()
        this.$refs.messages.loaded = true
      } else {
        this.updatePage(data)
      }

      if (scroll) {
        this.messageInfo.messages.splice(0, 0, ...data)
      } else {
        this.messageInfo.messages = data
        this.$store.commit("setLastIndex", this.lastIndex)
        this.$emit("chatRecentChange")
        this.messageViewToBottom()
      }
    },

    updatePage(list) {
      const lastMsg = list[0]
      this.messageInfo.page.chatIndexEnd = lastMsg
        ? lastMsg.chatIndex - 1
        : null
      this.messageInfo.page.chatIndexBegin = lastMsg.chatIndex - this.count
      this.messageInfo.page.lastCount = null
    },

    //判断是否有重复的消息
    isExisUUId(uuid) {
      if (!uuid) return false
      const index = this.messageInfo.messages.findIndex(
        (item) => item.uuid === uuid
      )
      return index > -1
    },

    //滚动到顶部
    async handleReachTop(next) {
      this.messageInfo.pageNumber = this.messageInfo.pageNumber + 1
      await this.getMessageByList(true)
      next()
    },
    //发送
    async _handleSend(content) {
      const message = this._createMessage(content)
      if (!this.$store.state.isGroup && !this.chatId) {
        await this.firstSendMessage()
        await this.$store.dispatch("getRecentChatList")
        await this.appendMessage(message, true)
      } else {
        await this.appendMessage(message, true)
      }
    },

    async firstSendMessage() {
      const res = await createChat({
        name: this.currentChatUserInfo.name,
        receiverId: this.currentChatUserInfo.id,
        isGroup: false,
        senderId: this.userId
      })
      if (res) {
        this.$store.commit("setChatId", res.data)
      }
    },

    _createMessage(message) {
      return {
        senderId: this.userId,
        receiverId: this.receiverId,
        sendTime: "",
        uuid: generateUUID(),
        senderName: this.userInfo.userName,
        senderAvatar: this.userInfo.avatar,
        receiverName: this.$store.getters.currentChatName,
        status: "ing",
        ...message,
        isGroup: this.$store.state.isGroup
      }
    },
    /**
     * 新增一条消息
     */
    async appendMessage(message, scrollToBottom = false) {
      this.messageInfo.messages.push(message)
      this.messageViewToBottom()
      let sendMessage
      if (message.status && message.status === "ing") {
        if (message.type !== MESSAGE_TYPE.FILE) {
          sendMessage = this.rmImageDomain(message)
        } else {
          await this.$nextTick()
          const data = await this.$refs.messages.$refs[
            message.uuid
          ][0].uploadFile()
          message.content = data
          message.status = "end"
          sendMessage = message
        }
        const res = await messagesSend(sendMessage)
        this.updateNewMessage(res.data)
        this.$store.commit("setLastIndex", this.lastIndex + 1)
        this.$store.commit("updateChatList", {
          ...res.data,
          senderName: sendMessage.senderName,
          contentText: sendMessage.contentText || sendMessage.content,
          receiverId: sendMessage.receiverId,
          type: sendMessage.type,
          id: this.chatId,
          unreadCount: 0
        })
      }
    },

    //撤回一条消息
    async handleRecall(message) {
      const res = await messagesRecall({ id: message.id })
      if (res) {
        this.$message.success("撤回成功")
        // if (message.isGroup == false) {
        //   this.removeMessage(message, false)
        // }
        this.removeMessage(message, message.isGroup)
      }
    },
    //重新编辑
    handleResetEdit(message) {
      this.$refs.editor.chatArea.clear()
      this.$refs.editor.chatArea.insertHtml(message)
      this.$refs.editor._checkSubmitDisabled()
    },

    //移除消息
    removeMessage(message, isGroup = true) {
      const index = this.messageInfo.messages.findIndex(
        (item) => item.id === message.id
      )
      if (index !== -1) {
        this.messageInfo.messages.splice(index, 1)
        if (!isGroup) {
          this.messageInfo.messages.push({
            ...message,
            type: MESSAGE_TYPE.RECALL,
            recallText: message.contentText,
            content: `你撤回了一条消息`
          })
          this.$store.commit("setLastIndex", this.lastIndex + 1)
          this.$store.commit("updateChatList", {
            ...message,
            senderName: "撤回通知",
            contentText: `你撤回了一条消息`,
            receiverId: message.receiverId,
            type: message.type,
            recallText: message.contentText,
            id: this.chatId,
            unreadCount: 0
          })
        }
      }
    },

    //接收的新消息
    receiverMessageAppend(data) {
      const message = this.addImageDomain(data)
      if (message.type === MESSAGE_TYPE.RECALL) {
        this.removeMessage(message.recallId)
      }
      this.appendMessage(message)
    },

    rmImageDomain(message) {
      const { content, ...rest } = message
      return {
        content: content.replace(this.minioEndpoint_mini, "[image]"),
        ...rest
      }
    },
    addImageDomain(message) {
      const { content, ...rest } = message
      return {
        content: content.replace("[image]", this.minioEndpoint_mini),
        ...rest
      }
    },
    //修改消息
    updateNewMessage(message) {
      const index = this.messageInfo.messages.findIndex(
        (item) => item.uuid === message.uuid
      )
      if (index >= 0) {
        this.$set(this.messageInfo.messages, index, {
          ...this.messageInfo.messages[index],
          sendTime: message.sendTime,
          id: message.id,
          status: "end"
        })
      }
    },

    _emitSend(message, next, file) {
      this.$emit(
        "send",
        message,
        (replaceMessage = { status: "succeed" }) => {
          next()
          this.updateMessage(Object.assign(message, replaceMessage))
        },
        file
      )
    },

    //
    _handleUpload(file) {
      const uploadLimit = lockr.get("systemInfo").uploadLimit
      if (file.size > uploadLimit * 1024 * 1024) {
        this.$message.error(`文件大小不能超过${uploadLimit}M`)
        return
      }
      const { type, fileType } = getFileType(file.name)
      let joinMessage
      if (type === FILE_TYPE.PIC || type === FILE_TYPE.VIDEO) {
        joinMessage = {
          fileSize: file.size,
          fileName: file.name,
          file: file,
          sendTime: new Date().getTime(),
          type: MESSAGE_TYPE.FILE,
          fileType: type,
          content: URL.createObjectURL(file)
        }
      } else {
        joinMessage = {
          fileSize: file.size,
          fileName: file.name,
          file: file,
          sendTime: new Date().getTime(),
          type: MESSAGE_TYPE.FILE,
          fileType: type,
          content: ""
        }
      }
      const message = this._createMessage(joinMessage)
      this.appendMessage(message, true)
    },
    async resetUploadSuccess(data) {
      const res = await messagesSend(data)
      this.updateNewMessage(res.data)
    },
    /**
     * 将当前聊天窗口滚动到底部
     */
    async messageViewToBottom() {
      this.$nextTick(() => {
        this.$refs.messages.scrollToBottom()
      })
    },
    handleMoreView() {
      this.groupRightShow = true
    },
    handleClose(done) {
      done()
    },
    closeHistory(done) {
      done()
      this.chatHistoryRightShow = false
    },
    historyShowChange() {
      this.chatHistoryRightShow = !this.chatHistoryRightShow
    }
  }
}
</script>
<style lang="less" scoped>
/deep/.el-drawer__header {
  margin-bottom: 0;
  padding: 14px 20px;
  border-bottom: 1px solid rgba(199, 205, 217, 0.3);
  font-size: 14px;
  color: #333333;
  font-weight: 600;
  .el-drawer__close-btn {
    font-size: 16px;
  }
}
.message-box {
  height: 100%;
  display: flex;
  flex: 1;
  flex-direction: column;
  background: #f3f3f3;
  position: relative;
}
.groupRight_Dilog {
  position: absolute;
  height: 100%;
  right: 0;
}

.fade-enter-active,
.fade-leave-active {
  transition: opacity 0.5s ease;
}
.fade-enter-from,
.fade-leave-to {
  opacity: 0;
}
</style>
